using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace CollabApp.Domain.Entities.Room;

/// <summary>
/// 房间聊天消息实体 - 存储房间内的聊天记录
/// </summary>
[Table("room_messages")]
public class RoomMessage : BaseEntity
{
    /// <summary>
    /// 关联房间ID - 外键，指向Rooms表
    /// </summary>
    [Required]
    [Column("room_id")]
    public Guid RoomId { get; private set; }

    /// <summary>
    /// 发送用户ID - 外键，指向Users表
    /// </summary>
    [Required]
    [Column("user_id")]
    public Guid UserId { get; private set; }

    /// <summary>
    /// 消息内容 - 聊天消息的具体文本内容
    /// </summary>
    [Required]
    [Column("message")]
    public string Message { get; private set; } = string.Empty;

    /// <summary>
    /// 消息类型 - 普通文本消息或系统消息
    /// </summary>
    [Column("message_type")]
    public MessageType MessageType { get; private set; } = MessageType.Text;

    // ============ 构造函数 ============

    /// <summary>
    /// 无参构造函数 - EF Core 必需
    /// </summary>
    private RoomMessage() { }

    /// <summary>
    /// 私有构造函数 - 仅限工厂方法调用
    /// </summary>
    /// <param name="roomId">房间ID</param>
    /// <param name="userId">用户ID</param>
    /// <param name="message">消息内容</param>
    /// <param name="messageType">消息类型</param>
    private RoomMessage(Guid roomId, Guid userId, string message, MessageType messageType = MessageType.Text)
    {
        RoomId = roomId;
        UserId = userId;
        Message = message;
        MessageType = messageType;
    }

    // ============ 导航属性 ============
    
    /// <summary>
    /// 关联的房间实体 - 多对一关系
    /// </summary>
    [ForeignKey("RoomId")]
    public virtual Room Room { get; set; } = null!;
    
    /// <summary>
    /// 发送消息的用户实体 - 多对一关系
    /// </summary>
    [ForeignKey("UserId")]
    public virtual Auth.User User { get; set; } = null!;

    // ============ 工厂方法 ============

    /// <summary>
    /// 创建用户消息 - 工厂方法
    /// </summary>
    /// <param name="roomId">房间ID</param>
    /// <param name="userId">用户ID</param>
    /// <param name="message">消息内容</param>
    /// <returns>新的用户消息实例</returns>
    public static RoomMessage CreateUserMessage(Guid roomId, Guid userId, string message)
    {
        if (roomId == Guid.Empty)
            throw new ArgumentException("房间ID不能为空", nameof(roomId));
        if (userId == Guid.Empty)
            throw new ArgumentException("用户ID不能为空", nameof(userId));
        if (string.IsNullOrWhiteSpace(message))
            throw new ArgumentException("消息内容不能为空", nameof(message));

        return new RoomMessage(roomId, userId, message, MessageType.Text);
    }

    /// <summary>
    /// 创建系统消息 - 工厂方法
    /// </summary>
    /// <param name="roomId">房间ID</param>
    /// <param name="message">系统消息内容</param>
    /// <returns>新的系统消息实例</returns>
    public static RoomMessage CreateSystemMessage(Guid roomId, string message)
    {
        if (roomId == Guid.Empty)
            throw new ArgumentException("房间ID不能为空", nameof(roomId));
        if (string.IsNullOrWhiteSpace(message))
            throw new ArgumentException("消息内容不能为空", nameof(message));

        // 系统消息使用空GUID作为用户ID
        return new RoomMessage(roomId, Guid.Empty, message, MessageType.System);
    }

    // ============ 业务方法 ============

    /// <summary>
    /// 检查是否为系统消息
    /// </summary>
    /// <returns>是否为系统消息</returns>
    public bool IsSystemMessage() => MessageType == MessageType.System;

    /// <summary>
    /// 检查是否为用户消息
    /// </summary>
    /// <returns>是否为用户消息</returns>
    public bool IsUserMessage() => MessageType == MessageType.Text;

    /// <summary>
    /// 获取消息长度
    /// </summary>
    /// <returns>消息字符数</returns>
    public int GetMessageLength() => Message?.Length ?? 0;

    /// <summary>
    /// 检查消息是否包含特定关键词
    /// </summary>
    /// <param name="keyword">关键词</param>
    /// <param name="ignoreCase">是否忽略大小写</param>
    /// <returns>是否包含关键词</returns>
    public bool ContainsKeyword(string keyword, bool ignoreCase = true)
    {
        if (string.IsNullOrWhiteSpace(keyword) || string.IsNullOrWhiteSpace(Message))
            return false;

        var comparison = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
        return Message.Contains(keyword, comparison);
    }

    /// <summary>
    /// 获取消息类型显示名称
    /// </summary>
    /// <returns>类型名称</returns>
    public string GetMessageTypeName()
    {
        return MessageType switch
        {
            MessageType.Text => "用户消息",
            MessageType.System => "系统消息",
            _ => "未知类型"
        };
    }
}

/// <summary>
/// 消息类型枚举
/// </summary>
public enum MessageType
{
    /// <summary>
    /// 普通文本消息 - 用户发送的聊天内容
    /// </summary>
    Text,
    
    /// <summary>
    /// 系统消息 - 由系统自动生成的通知消息
    /// </summary>
    System
}
